/*
*  This file is part of mangusta
*
*  mangusta is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  mangusta is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with mangusta; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
*
*  Author: <antonino.calderone@ericsson.com>, <acaldmail@gmail.com>
*
*/


/* -------------------------------------------------------------------------- */

#include "nu_variant.h"
#include "nu_functions.h"
#include "nu_os_std.h"
#include "nu_builtin_help.h"
#include "nu_lang_defs.h"

#include <functional>
#include <string>
#include <cstdlib>


#define NU_MODULE_DEF_FTIME(__item)\
   auto functor_get_##__item = [](\
      rt_prog_ctx_t & ctx,\
      const std::string& name,\
      const nu::func_args_t & args)\
   {\
      functions_t::check_arg_num(args, 0, name);\
      return nu::variant_t(int_t(\
         nu::_os_get_ ## __item()));\
   };

/* -------------------------------------------------------------------------- */

namespace nu
{

/* -------------------------------------------------------------------------- */

#define THIS_MODULE "time"
#define MD_NAMESPACE THIS_MODULE "."


/* -------------------------------------------------------------------------- */

static struct module_time_t : public module_t
{
   module_time_t()
   {
      add_module(this, THIS_MODULE);
   }

   virtual bool load() throw() override
   {
      auto & hmap = builtin_help_t::get_instance();

      hmap[ {lang_item_t::MODULE, THIS_MODULE}] =
      {
         "The " THIS_MODULE " module provides access to "
         "the system time functions",
         THIS_MODULE" module"
      };

      functions_t & fmap = functions_t::get_instance();

      NU_MODULE_DEF_FTIME(day);
      NU_MODULE_DEF_FTIME(month);
      NU_MODULE_DEF_FTIME(year);
      NU_MODULE_DEF_FTIME(wday);
      NU_MODULE_DEF_FTIME(yday);
      NU_MODULE_DEF_FTIME(hour);
      NU_MODULE_DEF_FTIME(min);
      NU_MODULE_DEF_FTIME(sec);
      NU_MODULE_DEF_FTIME(time);

      fmap[MD_NAMESPACE "day"] = functor_get_day;
      fmap[MD_NAMESPACE "month"] = functor_get_month;
      fmap[MD_NAMESPACE "year"] = functor_get_year;
      fmap[MD_NAMESPACE "wday"] = functor_get_wday;
      fmap[MD_NAMESPACE "yday"] = functor_get_yday;
      fmap[MD_NAMESPACE "hour"] = functor_get_hour;
      fmap[MD_NAMESPACE "min"] = functor_get_min;
      fmap[MD_NAMESPACE "sec"] = functor_get_sec;
      fmap[MD_NAMESPACE "get"] = functor_get_time;

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "month"}] =
      {
         "returns the month(from 0 to 11) for the system date, "
         "according to local time",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "month()"
      };


      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "year"}] =
      {
         "returns the year for the system date, according to local time",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "year()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "day"}] =
      {
         "returns the day for the system date, according to local time",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "day()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "wday"}] =
      {
         "returns the week day for the system date, according to local time",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "wday()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "yday"}] =
      {
         "returns the year day (1-365) for the system date, "
         "according to local time",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "SysYDay()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "hour"}] =
      {
         "returns the hour of day",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "hour()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "min"}] =
      {
         "returns the minute of current hour",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "min()"
      };

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "time"}] =
      {
         "returns a local time in seconds since the Epoch",
         PROGLANG_TYPE_INTEGER " " MD_NAMESPACE "time()"
      };


      //------------------------------------------------------------------

      auto functor_sys_time = [](
                                 rt_prog_ctx_t & ctx,
                                 const std::string& name,
                                 const nu::func_args_t & args)
      {
         functions_t::check_arg_num(args, 0, name);
         return nu::variant_t(_os_get_systime());
      };

      fmap[MD_NAMESPACE "now"] = functor_sys_time;

      hmap[ {lang_item_t::FUNCTION, MD_NAMESPACE "now"}] =
      {
         "returns a local time and date in the format 'DDD MMM DN HH:MM:SS YYYY'",
         PROGLANG_TYPE_STRING " " MD_NAMESPACE "now()"
      };

      return true;
   }

}
module_instance;


/* -------------------------------------------------------------------------- */

} // namespace nu

